package com.zxcl.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zxcl.domain.Prod;
import com.zxcl.domain.ProdTagReference;
import com.zxcl.domain.Sku;
import com.zxcl.dto.PageDTO;
import com.zxcl.dto.ProdAddDTO;
import com.zxcl.dto.ProdQueryDTO;
import com.zxcl.dto.PropQueryDTO;
import com.zxcl.ex.BusinessException;
import com.zxcl.mapper.ProdMapper;
import com.zxcl.mapper.ProdTagReferenceMapper;
import com.zxcl.mapper.SkuMapper;
import com.zxcl.model.ChangeStock;
import com.zxcl.model.ProdStock;
import com.zxcl.model.SkuStock;
import com.zxcl.service.impl.ProdService;
import com.zxcl.utils.AuthUtil;
import com.zxcl.vo.ProdSkuVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = "com.zxcl.service.ProdServiceImpl")
public class ProdServiceImpl extends ServiceImpl<ProdMapper, Prod> implements ProdService{



    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private ProdTagReferenceMapper prodTagReferenceMapper;

    @Autowired
    private ProdMapper prodMapper;

    /**
     * 分页查询商品信息
     *
     * @param pageDTO
     * @param prodQueryDTO
     * @return
     */
    @Override
    public Page<Prod> loadProdPage(PageDTO pageDTO, ProdQueryDTO prodQueryDTO) {
        Long shopId = AuthUtil.getShopId();//1L代表超级店铺(对所有商品分页查询)  否则就只查询当前店铺的
        Page<Prod> page=new Page<>(pageDTO.getCurrent(),pageDTO.getSize());
        return this.getBaseMapper().selectPage(page,new LambdaQueryWrapper<Prod>()
                .eq(!shopId.equals(1L),Prod::getShopId,shopId)
                .eq(!ObjectUtils.isEmpty(prodQueryDTO.getStatus()),Prod::getStatus,prodQueryDTO.getStatus())
                .like(!ObjectUtils.isEmpty(prodQueryDTO.getProdName()),Prod::getProdName,prodQueryDTO.getProdName())
                .orderByDesc(Prod::getUpdateTime)
        );
    }



    /**
     * 新增商品
     *
     * @param prodAddDTO
     * @return
     */

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Integer addProd(ProdAddDTO prodAddDTO) {
        Long shopId = AuthUtil.getShopId();
        //判断商品是否存在  按照指定的店铺查，管他是不是超级管理员
        Long count = getBaseMapper().selectCount(new LambdaQueryWrapper<Prod>()
                .eq(Prod::getShopId, shopId)
                .eq(Prod::getProdName, prodAddDTO.getProdName())
        );
        if (count>0){
            throw new BusinessException("该商品已存在");
        }

        ProdAddDTO.DeliveryModeVo deliveryModeVo = prodAddDTO.getDeliveryModeVo();
        prodAddDTO.setDeliveryMode(JSON.toJSONString(deliveryModeVo));
        prodAddDTO.setShopId(prodAddDTO.getShopId());
        int i = getBaseMapper().insert(prodAddDTO);
        handleSku(prodAddDTO);
        handleTagReference(prodAddDTO);
        return i;
    }

    /**
     * 修改商品
     * @param prodAddDTO
     * @return
     */
    @Override
    public Integer updateProd(ProdAddDTO prodAddDTO) {
        ProdAddDTO.DeliveryModeVo deliveryModeVo = prodAddDTO.getDeliveryModeVo();
        prodAddDTO.setDeliveryMode(JSON.toJSONString(deliveryModeVo));
        int i = getBaseMapper().updateById(prodAddDTO);
        handleSkuUpdate(prodAddDTO);
        handleTagReferenceUpdate(prodAddDTO);
        return i;
    }


    /**
     * 根据商品id查询商品和sku集合信息
     *
     * @param prodId
     * @return
     */
    @Override
    @Cacheable(key = "#prodId")
    public ProdSkuVO getProdAndSkus(Long prodId) {
        //主键id去数据库中查询也快
        Prod prod = prodMapper.selectById(prodId);
        ProdSkuVO prodSkuVO = new ProdSkuVO();
        BeanUtils.copyProperties(prod, prodSkuVO);
        List<Sku> skus = skuMapper.selectList(new LambdaQueryWrapper<Sku>()
                .eq(Sku::getProdId, prodId)
                .eq(Sku::getStatus, 1)
        );
        prodSkuVO.setSkuList(skus);
        return prodSkuVO;

    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 修改库存
     *
     * @param changeStock
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean changeStocks(ChangeStock changeStock) {
        List<SkuStock> skuStocks = changeStock.getSkuStocks();
        skuStocks.forEach(skuStock -> {
            //这里是它说的更新行锁的位置
            int row=skuMapper.updateStock(skuStock.getSkuId(),skuStock.getCount());
            if(row<=0){
                throw new BusinessException("商品"+skuStock.getProdName()+"库存不足");
            }
        });
        List<ProdStock> prodStocks = changeStock.getProdStocks();
        prodStocks.forEach(prodStock -> {
            int row=this.getBaseMapper().updateTotalStock(prodStock.getProdId(),prodStock.getCount());
            if(row<=0){
                throw new BusinessException("修改prod的库存失败");
            }
        });
        //删除缓存
        List<String> cacheKeys = prodStocks.stream().map(prodStock -> "com.zxcl.service.impl.ProdServiceImpl::" + prodStock.getProdId()).collect(Collectors.toList());
        stringRedisTemplate.delete(cacheKeys);
        return true;
    }



    /**
     * 处理标签关系
     *
     * @param prodAddDTO
     */
    private void handleTagReference(ProdAddDTO prodAddDTO) {
        List<Long> tagList = prodAddDTO.getTagList();
        if (CollectionUtils.isEmpty(tagList)) {
            return;
        }
        Long prodId = prodAddDTO.getProdId();
        tagList.forEach(tid -> {
            ProdTagReference prodTagReference = new ProdTagReference();
            prodTagReference.setTagId(tid);
            prodTagReference.setProdId(prodId);
            prodTagReference.setStatus(true);
            prodTagReference.setCreateTime(new Date());
            prodTagReference.setShopId(prodAddDTO.getShopId());
            prodTagReferenceMapper.insert(prodTagReference);
        });


    }
    /**
     * 处理sku表
     *
     * @param prodAddDTO
     */
    private void handleSku(ProdAddDTO prodAddDTO) {
        List<Sku> skuList = prodAddDTO.getSkuList();
        if (CollectionUtils.isEmpty(skuList)) {
            return;
        }
        Long prodId = prodAddDTO.getProdId();
        skuList.forEach(sku -> {
            sku.setCreateTime(new Date());
            sku.setUpdateTime(new Date());
            sku.setProdId(prodId);
            skuMapper.insert(sku);
        });
    }


    /**
     * 处理sku表 修改
     * @param prodAddDTO
     */
    private void handleSkuUpdate(ProdAddDTO prodAddDTO) {


        List<Sku> skuList = prodAddDTO.getSkuList();
        Long prodId = prodAddDTO.getProdId();
        skuMapper.deleteById(prodId);
        skuList.forEach(sku -> {
            sku.setCreateTime(new Date());
            sku.setUpdateTime(new Date());
            sku.setProdId(prodId);
            skuMapper.insert(sku);
        });
    }
    /**
     * 处理标签关系表 修改
     * @param prodAddDTO
     */
    private void handleTagReferenceUpdate(ProdAddDTO prodAddDTO) {
        List<Long> tagList = prodAddDTO.getTagList();
        Long prodId = prodAddDTO.getProdId();
        prodTagReferenceMapper.deleteById(prodId);
        tagList.forEach(tid -> {
            ProdTagReference prodTagReference = new ProdTagReference();
            prodTagReference.setTagId(tid);
            prodTagReference.setProdId(prodId);
            prodTagReference.setStatus(true);
            prodTagReference.setCreateTime(new Date());
            prodTagReference.setShopId(prodAddDTO.getShopId());
            prodTagReferenceMapper.insert(prodTagReference);
        });
    }
}
